/**
 * TabVD is a Virtual Desktop Client/Server designed specifically for connecting
 * from Tablet like devices.
 *
 * Copyright (C) 2011 Subhabrata Ghosh
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * AbstractLogger.h
 *
 *  Created on: May 26, 2011
 *      Author: subhagho
 */

#ifndef ABSTRACTLOGGER_H_
#define ABSTRACTLOGGER_H_

#include "IConfigurable.h"
#include "DateTime.h"

namespace tabvd {
    /* --------------------------------------------------------------------------*/
    /**
    * @Synopsis  Log Level Enumeration.
    */
    /* ----------------------------------------------------------------------------*/
    enum ELevel {
        LOGLEVEL_DEBUG = 0, LOGLEVEL_WARNING = 1, LOGLEVEL_ERROR = 2, LOGLEVEL_PRINT = 9999
    };

    /* --------------------------------------------------------------------------*/
    /**
    * @Synopsis  Abstract base class for loggers.
    */
    /* ----------------------------------------------------------------------------*/
    class AbstractLogger : public IConfigurable {
        public:

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Set the log level.
            *
            * @Param level
            */
            /* ----------------------------------------------------------------------------*/
            void setlevel(ELevel level);

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Abstract method, to be implemented to initialize the logger.
            *
            * @Param config
            *
            * @Returns   
            */
            /* ----------------------------------------------------------------------------*/
            virtual void init(AbstractConfiguration* config) = 0;

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Abstract log method with variable arguments.
            *
            * Format string specifies the output format similar to the printf() function.
            *
            * @Param level
            * @Param format
            * @Param ...
            */
            /* ----------------------------------------------------------------------------*/
            virtual void log(ELevel level, const char* format, ...) = 0;

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Abstract print method.
            * 
            * Print any arbitary message to the log file. This function doesn't 
            * adhere to any logging level and should not be used frequently.
            * Format resembles the format string for printf().
            * 
            *
            * @Param format
            * @Param ...
            */
            /* ----------------------------------------------------------------------------*/
            virtual void print(const char* format, ...) = 0;

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Abstract method, clear the contents of the log.
            */
            /* ----------------------------------------------------------------------------*/
            virtual void clear() = 0;

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Abstract method, to backup the contents of the log.
            *
            * This method will backup the contents of the log and clear the logger.
            */
            /* ----------------------------------------------------------------------------*/
            virtual void backup() = 0;

            virtual ~AbstractLogger();

        protected:
            ELevel loglevel;
            bool isrunning;
            AbstractLogger();

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Get the formatted message string.
            *
            * @Param level
            * @Param format
            * @Param args
            *
            * @Returns   
            */
            /* ----------------------------------------------------------------------------*/
            virtual std::string* getmessage(ELevel level, const char* format, va_list args);

            /* --------------------------------------------------------------------------*/
            /**
            * @Synopsis  Check if the current logging level is greater than the passed level.
            *
            * @Param level
            *
            * @Returns   
            */
            /* ----------------------------------------------------------------------------*/
            bool shouldlog(ELevel level);

    };

    const int _MAX_MESG_BUFFER_SZ_ = 2048;

}

// Convinience Log function Macros
#define LPDEBUG(logger, fmt, ...) logger->log(tabvd::LOGLEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LPWARNING(logger, fmt, ...) logger->log(tabvd::LOGLEVEL_WARNING, fmt, ##__VA_ARGS__)
#define LPERROR(logger, fmt, ...) logger->log(tabvd::LOGLEVEL_ERROR, fmt, ##__VA_ARGS__)

#define LDEBUG(logger, fmt, ...) logger.log(tabvd::LOGLEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LWARNING(logger, fmt, ...) logger.log(tabvd::LOGLEVEL_WARNING, fmt, ##__VA_ARGS__)
#define LERROR(logger, fmt, ...) logger.log(tabvd::LOGLEVEL_ERROR, fmt, ##__VA_ARGS__)

#define LSDEBUG(logger, mesg) logger.log(tabvd::LOGLEVEL_DEBUG, ":%s:%d:%s", __FILE__, __LINE__, mesg)
#define LSWARNING(logger, mesg) logger.log(tabvd::LOGLEVEL_WARNING, ":%s:%d:%s", __FILE__, __LINE__, mesg)
#define LSERROR(logger, mesg) logger.log(tabvd::LOGLEVEL_ERROR, ":%s:%d:%s", __FILE__, __LINE__, mesg)

#define LPSDEBUG(logger, mesg) logger->log(tabvd::LOGLEVEL_DEBUG, ":%s:%d:%s", __FILE__, __LINE__, mesg)
#define LPSWARNING(logger, mesg) logger->log(tabvd::LOGLEVEL_WARNING, ":%s:%d:%s", __FILE__, __LINE__, mesg)
#define LPSERROR(logger, mesg) logger->log(tabvd::LOGLEVEL_ERROR, ":%s:%d:%s", __FILE__, __LINE__, mesg)

#endif /* ABSTRACTLOGGER_H_ */
